#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

const int N = 5010;

int a, b;              //存储输入
vector<int> c;         //存储输出
int prime[N], cnt = 0; //存储质数
bool st[N];            //线性筛标记
int num[N];            //存储质数对应的数量

void get_prime(int n) //线性筛函数
{
    memset(st, false, sizeof st); //清空标记数组
    for (int i = 2; i <= n; ++i)  //遍历所有可能是质数的数
    {
        if (!st[i])                             //如果还没有被筛去
            prime[cnt++] = i;                   //那么它就是质数
        for (int j = 0; prime[j] <= n / i; ++j) //n/i是为了方式后面访问st的时候爆掉
        {
            st[prime[j] * i] = true; //将这个质数的倍数筛掉
            if (i % prime[j] == 0)
                break;
        }
    }
    return;
}

int get_num(int n, int p) //算出n!中有几个p
{
    int res = 0;
    while (n)
    {
        res += n / p;
        n /= p; //这一步除以p，下一轮计算再除以p，就等价于除以p^2了，以此类推
    }
    return res;
}

vector<int> mul(vector<int> &A, int &B)
{
    vector<int> C; //存储答案
    int t = 0;     //存储进位
    for (int i = 0; i < A.size(); ++i)
    {
        t = t + A[i] * B;    //计算当前位的计算数值
        C.push_back(t % 10); //计算当前位保留的数
        t /= 10;             //计算进位值
    }
    while (t) //最后的进位不一定是个位，所以要把各位拆开塞进去
    {
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0) //如果最高位为0，或者只剩下一个数了
        C.pop_back();                     //那么就把最高位的0去掉
    return C;
}

int main()
{
    freopen("cin.txt", "r", stdin);
    c.push_back(1); //初始化存储答案的数组
    cin >> a >> b;
    get_prime(a); //初始化prime数组
    for (int i = 0; i < cnt; ++i)
        num[i] = get_num(a, prime[i]) - get_num(b, prime[i]) - get_num(a - b, prime[i]); //计算出组合数中的prime的数量
    for (int i = 0; i < cnt; ++i)
        for (int j = 0; j < num[i]; ++j)
            c = mul(c, prime[i]); //累乘质因数
    for (int i = c.size() - 1; i >= 0; --i)
        cout << c[i];
    return 0;
}